#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "hw_uart.h"
#include "..\osram96x16x1.h"
#include "debug.h"
#include "interrupt.h"
#include "sysctl.h"
#include "uart.h"
#include "gpio.h"
#include "timer.h"
#include "timers.h"
#include "uart_clock.h"	
#include "uart_menu.h"


//
// Define clock
//
clock displayTimer;

//
//Define flag for first time initialization
//
unsigned int t_flag = 1;
unsigned int check_flag = 1;
unsigned int funcFlag = 1;

//
//Array for saving inputs from the user about programs
//
clock schedule[3] = {0};

//
//Array for saving outputs from the user about programs
//
clock kill[3] = {0};	

//
//Array of functions
//
void (*funcArr[3])(int) = {&Paint, &Calc, &Minesweeper};


clock simulate(clock tmpStr)
{
	clock tmp; 

	if ((tmpStr.sec + 20) > 59)
	{
		tmp.sec = 20 - (60 - tmpStr.sec);
		if (tmpStr.min == 59)
		{
			tmp.min = 0;
			if (tmpStr.hour == 23)
			{
				tmp.hour = 0;
			}
			else 
			{
				tmp.hour = tmpStr.hour + 1;
			}
		}
		else
		{
			tmp.min = tmpStr.min + 1;
			tmp.hour = tmpStr.hour;
		}
	}
	else 
	{
		tmp.sec = tmpStr.sec + 20;
		tmp.min = tmpStr.min;
		tmp.hour = tmpStr.hour;
	}

	return tmp;
}
//*****************************************************************************
//
// The interrupt handler for the first timer interrupt.
//
//*****************************************************************************
void
Timer0IntHandler(void)
{
    //
    // Clear the timer interrupt.
    //
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
	
    //
    // Update the interrupt status on the display.
    //
    IntMasterDisable();
    displayTime(displayTimer, t_flag);
    IntMasterEnable();
}

//*****************************************************************************
//
//Convert integer into string.
//
//*****************************************************************************
void itoa(unsigned long tmpInt, char * text)
{
	int x,y,tmp = tmpInt;
	
	y = tmp%10;
	tmp -= y;
	if (!tmp)
	{
		text[0] = 48;
		text[1] = y+48;
		text[2] = '\0';
	}	
	else 
	{
		x = (tmp/10)%10;
		text[0] = x + 48;
		text[1] = y + 48;
		text[2] = '\0';
	}
}

//*****************************************************************************
//
//Display structure to the OLED.
//
//*****************************************************************************
void _displayTime(clock tmpStr,int check_flag)
{
	char tmpArr[3] = {0};

	// Drawing hours
	itoa(tmpStr.hour,tmpArr);
	OSRAM96x16x1StringDraw(tmpArr,12,1);
	OSRAM96x16x1StringDraw(":",24,1);
				
	//Drawing minutes
	itoa(tmpStr.min,tmpArr);
	OSRAM96x16x1StringDraw(tmpArr,30,1);
	OSRAM96x16x1StringDraw(":",42,1);
		
	//Drawing seconds
	itoa(tmpStr.sec++,tmpArr);
	OSRAM96x16x1StringDraw(tmpArr,48,1);

	//Drawing mode ON
	if(!check_flag)
		OSRAM96x16x1StringDraw("ON ", 78, 1);
	else OSRAM96x16x1StringDraw("OFF", 78, 1);
	check_flag = 0;
}

//*****************************************************************************
//
// Checks time and call for _displayTimer function.
//
//*****************************************************************************
void displayTime(clock tmpStruct, unsigned int tmp)
{
	int i;
	
	t_flag = tmp;
	if (t_flag)
	{		

		OSRAM96x16x1Clear();
		displayTimer.sec = tmpStruct.sec - 1;
		displayTimer.min = tmpStruct.min;
		displayTimer.hour = tmpStruct.hour;
		t_flag = 0;
		_displayTime(tmpStruct, 1);

	}
	else 
	{
		if (displayTimer.sec == 59)		// changes minutes
		{
			displayTimer.sec = 0;
			if (displayTimer.min == 59) // changes hours
			{
				displayTimer.min = 0;
				if (displayTimer.hour == 23) //	00 hours
				{
					displayTimer.hour = 0;
					_displayTime(displayTimer, 0);
				}
				else 
				{
					++displayTimer.hour;
					_displayTime(displayTimer, 0);
				}
			}
			else 
			{
				++displayTimer.min;
				_displayTime(displayTimer, 0);
			}
		}
		else
		{
			++displayTimer.sec;
			_displayTime(displayTimer, 0);
		}			
	}
	for (i = 0; i < 3; ++i)
	{
		if ((schedule[i].hour == displayTimer.hour) 
		&& (schedule[i].min == displayTimer.min) 
		&& (schedule[i].sec == displayTimer.sec))
		{	
				funcFlag = 1;
				funcArr[i](funcFlag);		
		}
		if ((kill[i].hour == displayTimer.hour) 
		&& (kill[i].min == displayTimer.min) 
		&& ((kill[i].sec)== displayTimer.sec))
		{	
				funcFlag = 0;
				funcArr[i](funcFlag);	
		}	
	}  
}

//*****************************************************************************
//
//Enter data to the Array for check.
//
//*****************************************************************************
void inputArray(clock tmpStruct, unsigned short number)
{
	clock tmp;	

	schedule[number - 1].hour = tmpStruct.hour;	
	schedule[number - 1].min = tmpStruct.min;
	schedule[number - 1].sec = tmpStruct.sec;

	tmp = simulate(tmpStruct);
	kill[number - 1].hour = tmp.hour;
	kill[number - 1].min = tmp.min;
	kill[number - 1].sec = tmp.sec;
}

void Timer1IntHandler(void)
{
	//
    // Clear the timer interrupt.
    //
    TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

	button_flag = 1;
	GPIOPinIntClear(GPIO_PORTC_BASE, GPIO_PIN_4);
	GPIOPinIntEnable(GPIO_PORTC_BASE, GPIO_PIN_4);
}

void GPIOCIntHandler(void)
{
    //
    // Clear the GPIO interrupt.
    //
    GPIOPinIntClear(GPIO_PORTC_BASE, GPIO_PIN_4);
	
	//
	//Forbid interrupt by the button
	//
	GPIOPinIntDisable(GPIO_PORTC_BASE, GPIO_PIN_4);
	
	TimerEnable(TIMER1_BASE, TIMER_A);
}
